﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MediaBrowser.Library.Persistance;
using MediaBrowser.Library.Entities;
using MusicPlugin.Util;
using MusicPlugin.Code;
using MediaBrowser.Library.Logging;
using MediaBrowser.Library;
//using MusicPlugin.ThemeModelItemInterfaces;
using MusicPlugin.LibraryManagement;
using TagLib;
using MediaBrowser.Library.ImageManagement;
using System.IO;
using System.Drawing;

namespace MusicPlugin.Library.Entities
{
    public class Song : Music//, IMusicModelItem
    {

        public Song()
            : base()
        {
            if (!string.IsNullOrEmpty(Settings.Instance.SongImage))
                this.PrimaryImagePath = Settings.Instance.SongImage;
            
        }
        public override string LongName
        {
            get
            {
                string longName = base.LongName;
                if (Parent != null)
                {
                    longName = Parent.Name + " - " + longName;
                }
                return longName;
            }
        }

        [Persist]
        public string Album { get; set; }
        [Persist]
        public string Artist { get; set; }
        [Persist]
        public string Comments { get; set; }
        [Persist]
        public List<string> Genres { get; set; }
        [Persist]
        public string Lyrics { get; set; }
        [Persist]
        public string Title { get; set; }
        [Persist]
        public string ProductionYear { get; set; }
        [Persist]
        public string Track { get; set; }
        [Persist]
        public int DurationInt { get; set; }        
        [Persist]
        public string Bitrate { get; set; }
        [Persist]
        public string FileType { get; set; }
        [Persist]
        public string BeatsPerMinute { get; set; }
        [Persist]
        public string Composers { get; set; }
        [Persist]
        public string Performers { get; set; }
        [Persist]
        public string Conductor { get; set; }

        public string Duration
        {
            get { return MusicHelper.SecondsToHighestTwoUnits(DurationInt); }
        }

        [Persist]
        DateTime lastUpdated = DateTime.MinValue;

        public override bool RefreshMetadata(MediaBrowser.Library.Metadata.MetadataRefreshOptions options)
        {
            bool force = options == MediaBrowser.Library.Metadata.MetadataRefreshOptions.Force;
            if (!force && this.lastUpdated.CompareTo(this.MediaLocation.DateModified) > 0)
                return false;
            
            if ((options == MediaBrowser.Library.Metadata.MetadataRefreshOptions.Default)||
                (force)
                )
            {
                if (Settings.Instance.UseId3Tags)
                {
                    TagLib.File file = null;

                    // Read tag information
                    try
                    {
                        Logger.ReportInfo("MusicPlugin going to read tag for " + this.MediaLocation.Path);
                        file = TagLib.File.Create(this.MediaLocation.Path);
                        FileType = System.IO.Path.GetExtension(this.MediaLocation.Path).ToUpper();
                    }
                    catch (UnsupportedFormatException)
                    {
                        Logger.ReportInfo("MusicPlugin cannot read file tag " + this.MediaLocation.Path + " file type not supported.");
                        return false;
                    }

                    catch (CorruptFileException)
                    {
                        Logger.ReportInfo("MusicPlugin cannot read file tag " + this.MediaLocation.Path + " file header corrupt.");
                        return false;
                    }
                    catch (Exception e)
                    {
                        Logger.ReportException("MusicPlugin cannot read file tag " + this.MediaLocation.Path, e);
                        return false;
                    }

                    if (file!= null)
                        CopyId3TagInfo(file.Tag, file.Properties);

                    // Read lyrics information.
                    //if (string.IsNullOrEmpty(Lyrics))
                    //{
                    //    string lyrics = MusicHelper.GetLyrics(Artist, Title);
                    //    Lyrics = string.IsNullOrEmpty(lyrics) ? string.Empty : lyrics;
                    //    Logger.ReportInfo("MusicPlugin lyrics for " + Artist + "-" + Title + "=" + lyrics);
                    //}
                }

                
            }
            return true;
        }

        private void CopyId3TagInfo(TagLib.Tag tag, TagLib.Properties properties)
        {
            if (tag == null)
                return;

            Album = tag.Album;
            if (tag.AlbumArtists != null && tag.AlbumArtists.Length > 0)
                Artist = tag.AlbumArtists[0];
            
            if (tag.Genres != null && tag.Genres.Length > 0)
            {
                if (Genres == null)
                    Genres = new List<string>();
                Genres = tag.Genres.ToList<string>();
            }

            if (properties != null)
            {
                try
                { DurationInt = properties.Duration == null ? 0 : Convert.ToInt16(properties.Duration.TotalSeconds); }
                catch
                { DurationInt = 0; }
                Bitrate = properties.AudioBitrate.ToString();                
            }
            
            Comments = tag.Comment;            
            Title = tag.Title;
            Overview = Lyrics = tag.Lyrics;// string.IsNullOrEmpty(tag.Lyrics) ? MusicHelper.GetChartLyricsLyrics(Artist, Title) : tag.Lyrics;
            ProductionYear = tag.Year.ToString();
            BeatsPerMinute = tag.BeatsPerMinute.ToString();
            Composers = tag.JoinedComposers;
            Performers = tag.JoinedPerformers;
            Conductor = tag.Conductor;            
            Track = tag.Track.ToString();
            Name = BuildItemName();

            if (Settings.Instance.UseEmbeddedTagImage)
            {
                string imageFilePath = PersistTagArt(tag);
                if (!string.IsNullOrEmpty(imageFilePath))
                {
                    PrimaryImagePath = imageFilePath;
                    Logger.ReportInfo("MusicPlugin setting image " + imageFilePath + " for " + imageFilePath, this.MediaLocation.Path);
                }
            }
            
            this.lastUpdated = DateTime.Now;
            OnMetadataChanged(null);
            Kernel.Instance.ItemRepository.SaveItem(this);
        }

        private string PersistTagArt(Tag tag)
        {
            if (tag.Pictures != null && tag.Pictures.Count() > 0)
            {
                try
                {
                    string localFolder = System.IO.Path.GetDirectoryName(this.MediaLocation.Path);
                    string localCache = System.IO.Path.Combine(localFolder, "Metadata");
                    if (Directory.Exists(localFolder))
                    {
                        Directory.CreateDirectory(localCache);
                        (new DirectoryInfo(localCache)).Attributes = FileAttributes.Directory | FileAttributes.Hidden; 
                    }

                    foreach (var item in tag.Pictures)
	                {
                        if (item.Type.Equals(PictureType.FrontCover))
                            return PersistPicture(localCache, item);
	                }

                    if (tag.Pictures != null && tag.Pictures.Count() > 0)
                    {
                        Logger.ReportInfo("MusicPlugin cannot find FrontCover type art. Using first image on tag");
                        return PersistPicture(localCache, tag.Pictures[0]);
                    }


                }
                catch (Exception e)
                { Logger.ReportException("MusicPlugin album art caching failed:", e); }
            }
            return null;
        }

        private string PersistPicture(string localAppFolderCache, IPicture item)
        {
            if (item != null && item.Data != null && item.Data.Data != null)
            {
                string imageName = System.IO.Path.Combine(localAppFolderCache, System.IO.Path.GetFileNameWithoutExtension(this.MediaLocation.Path) + ".jpg");

                if (System.IO.File.Exists(imageName))
                    return imageName;

                Stream stream = new MemoryStream(item.Data.Data);
                using (Image img = Image.FromStream(stream))
                {
                    img.Save(imageName);
                    Logger.ReportInfo("MusicPlugin cached the following image " + imageName + " for " + this.Name);
                    return imageName;
                }
            }
            return null;
        }

        private string BuildItemName()
        {
            string newName = Settings.Instance.NormalLibraryDisplayFormat;
            if (string.IsNullOrEmpty(newName))
                return Name;
            
            int replaceCount = 0;
                        
            foreach (var item in Global.Indexes)
            {
                if (newName.Contains(item))
                {
                    //todo: remove indexers in item name.
                    if (item.Equals(Global.TITLE_INDEX, StringComparison.CurrentCultureIgnoreCase)
                        && !string.IsNullOrEmpty(Title))
                    {
                        newName = newName.Replace(item, Title);
                        replaceCount++;
                    }
                    else if (item.Equals(Global.TRACK_INDEX, StringComparison.CurrentCultureIgnoreCase)
                        && !string.IsNullOrEmpty(Title))
                    {
                        newName = newName.Replace(item, Track.PadLeft(2,'0'));
                        replaceCount++;
                    }
                    else if (item.Equals(Global.ALBUM_INDEX, StringComparison.CurrentCultureIgnoreCase)
                        && !string.IsNullOrEmpty(Album))
                    {
                        newName = newName.Replace(item, Album);
                        replaceCount++;
                    }
                    else if (item.Equals(Global.ARTIST_INDEX, StringComparison.CurrentCultureIgnoreCase)
                        && !string.IsNullOrEmpty(Artist))
                    {
                        newName = newName.Replace(item, Artist);
                        replaceCount++;
                    }
                    
                }
            }

            if (replaceCount > 0)
                return newName;
            return Name;
        }
        
    }

}
